### Lazy evaluation with Iterators In this section of the CS50 course, we take a look at the python syntax, its data types and some more elaborated structures like lists and dictionnaries. Coding in Python after C, allows you to better appreciate a higher level of abstraction. Programs that required a tidious implementation in C, are done in a few Python lines. Python introduces exceptions, object oriented programming, resolves the issue of Integer overflow (but not the problem of floating point imprecision) and possesses a broad range of librairies that allows us to stand on the shoulder of giants. But I would like to talk about a feature that was not mention in CS50 which is the Iterators. An iterator is an object that allows you to loop through a sequence of data without having to store it in memory. This behavior is called lazy evaluation and it is very useful when we want to loop over a very large or infinite data set (used a lot in data science). Take a look at the below implementation that is **NOT** using iterators: ``` def createData(bigNumber): sequence = [] for i in range(bigNumber): sequence.append(i * i) return sequence def loopWithoutIterator(bigNumber): for value in createData(bigNumber): if(value > 100): break print(value) loopWithoutIterator(1000000) ``` \# Here we make a million calculation that we store in an array and then we loop over this array set and print out the first eleven values. Now let's take a look at the strength of iterators: ``` def createIterator(bigNumber): for i in range(bigNumber): yield i * i def loopWithIterator(bigNumber): for i in createIterator(bigNumber): if i > 100: break print(i) loopWithIterator(1000000) ``` \# Here the iterator will yield one value on each outer iteration, and if the value is smaller than 100 it will print it. So instead of making 1000 000 calculation + 11 print out it will do 11 calculation + 11 print outs ![small](/images/python.png)